package com.szzg10.webservice.chapter4;

import java.beans.XMLEncoder;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class RabbitCounterServlet extends HttpServlet {

	private Map<Integer, Integer> cache;
	
	@Override
	public void init() throws ServletException {
		super.init();
		cache = Collections.synchronizedMap(new HashMap<Integer, Integer>());
	}
	
	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String strNum = request.getParameter("nums");
		strNum = strNum.substring(1);
		strNum = strNum.substring(0, strNum.length() - 1);
		
		String[] nums = strNum.split(",");
		for(int i = 0; i < nums.length; i++) {
			Integer num = Integer.parseInt(nums[i].trim());
			countRabbit(num);
		}
		
		sendTypedResponse(request, response, cache.values().toString());
	}
	
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		sendTypedResponse(request, response, cache.values().toString());
	}
	
	@Override
	protected void doDelete(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		cache.clear();
		
		sendTypedResponse(request, response, "Cache is deleted!");
	}
	
	private int countRabbit(int n) {
		if(n < 2) {
			return n;
		}
		else if(cache.containsKey(n)) {
			return cache.get(n);
		}
		else if(cache.containsKey(n - 1) && cache.containsKey(n - 2)) {
			int result = cache.get(n - 1) + cache.get(n - 2);
			cache.put(n, result);
			
			return result;
		}
		else {
			int prev = 0;
			int fib = 1;
			for(int i = 2; i <= n; i++) {
				int temp = fib;
				fib = prev + fib;
				prev = temp;
			}
			
			cache.put(n, fib);
			return fib;
		}
	}
	
	private void sendTypedResponse(HttpServletRequest request, HttpServletResponse response, String data) throws IOException {
		String request_typed = request.getHeader("accept");
		if(request_typed.contains("text/plain")) {
			sendPlain(request, response, data);
		}
		else if(request_typed.contains("text/html")) {
			sendHtml(request, response, data);
		}
		else {
			sendXml(request, response, data);
		}
	}
	
	private void sendPlain(HttpServletRequest request, HttpServletResponse response, String data) throws IOException {
		ServletOutputStream out = response.getOutputStream();
		
		out.write(data.getBytes());
		out.flush();
		
		out.close();
	}
	
	private void sendHtml(HttpServletRequest request, HttpServletResponse response, String data) throws IOException {
		String html_start = "<html><body>";
		String html_doc = data;
		String html_end = "</body></html>";
		
		String html = html_start + html_doc + html_end;
		sendPlain(request, response, html_doc);
	}
	
	private void sendXml(HttpServletRequest request, HttpServletResponse response, String data) throws IOException {
		XMLEncoder xmlEncoder = new XMLEncoder(response.getOutputStream());
		xmlEncoder.writeObject(data.toString());
		xmlEncoder.close();
	}
}
